
#include "OLApplication.h"
#include "OLAppTemplateDefs.h"
#include "OLStatusbar.h"
#include "OLToolbar.h"
#include "OLButton.h"
#include "OLModalBackground.h"
#include "OLMenuPane.h"
#include "OLSplashScreen.h"
#include "OLPixmapWidget.h"
#include "OLView.h"
#include "OLMainWindow.h"
#include "OLMenuSurface.h"
#include "OLDialogSurface.h"
#include "OLBannerSurface.h"
#include "OLSpinnerSurface.h"
#include "OLInfoPanelSurface.h"

#include <QtGui/QFont>
#include <QtGui/QPalette>
#include <QtGui/QVBoxLayout>
#include <QtCore/QStateMachine>
#include <QtCore/QTimer>
#include <QtCore/QPropertyAnimation>
#include <QtCore/QSignalTransition>
#include <QtGui/QLabel>
#include <QtCore/QSignalMapper>
#include <QtCore/QParallelAnimationGroup>
#include <QtGui/QFontDatabase>
#include <QPushButton>

// Task switcher if symbian only
#ifdef Q_OS_SYMBIAN
#include <e32event.h>
#include <e32std.h>
#include <e32keys.h>
#include <e32svr.h>
#endif

OLApplication::OLApplication(int& argc, char *argv[])
    : QApplication(argc, argv), m_obj(0), m_miniToolbar(false), m_toolbarBottomPos(true)
{
    // add the application fonts
    QFont f = font();
    f.setPixelSize(FONT_SIZE);
    setFont(f);

    QPalette palette(OLApplication::palette());
    palette.setColor(QPalette::WindowText, Qt::white);
    palette.setColor(QPalette::Background, Qt::black);
    OLApplication::setPalette(palette);

    m_mainwidget = new OLMainWindow();
    connect(m_mainwidget, SIGNAL(handleResize()), this, SLOT(appResized()));
    connect(m_mainwidget, SIGNAL(handlePortraitSwitch()), this, SLOT(handleSwitchToPortrait()));
    connect(m_mainwidget, SIGNAL(handleLandscapeSwitch()), this, SLOT(handleSwitchToLandscape()));

    m_statusbar = new OLStatusbar(m_mainwidget);
    m_statusbar->setFixedHeight(STATUSBAR_HEIGHT);

    m_toolbar = new OLToolbar(m_mainwidget);

    m_appWindow = new OLView(m_mainwidget);

    QVBoxLayout* layout = new QVBoxLayout();
    layout->setContentsMargins(0,0,0,0);
    layout->setSpacing(0);

    layout->addWidget(m_statusbar);
    layout->addWidget(m_appWindow);
    layout->addWidget(m_toolbar);
    m_mainwidget->setLayout(layout);

    OLSplashScreen* splashScreen = new OLSplashScreen(m_mainwidget);
    connect(m_mainwidget, SIGNAL(handleResize()), splashScreen, SLOT(handleAppResize()));

    m_mainwidget->showMainWindow();
}

OLApplication::~OLApplication()
{
    delete m_mainwidget;
}

QString OLApplication::windowTitle() const
{
    return m_mainwidget->windowTitle();
}

void OLApplication::setWindowTitle(const QString& title)
{
    m_mainwidget->setWindowTitle(title);
    emit titleChanged(title);
}

QSize OLApplication::viewSize() const
{
    return m_appWindow->size();
}

OLApplication::OrientationOptions OLApplication::orientation() const
{
    return m_mainwidget->orientation();
}

void OLApplication::removeStackedView()
{
    m_appWindow->back();
}

// ---------------------------
// Splash screen handling
// ---------------------------

void OLApplication::changeSplashScreenImage(const QString& pixmap)
{
    OLSplashScreen* splashScreen = m_mainwidget->findChild<OLSplashScreen*>();
    if(splashScreen)
        splashScreen->changeSplashScreenImage(pixmap);
}

void OLApplication::changeSplashScreenLayout(QLayout* layout)
{
    OLSplashScreen* splashScreen = m_mainwidget->findChild<OLSplashScreen*>();
    if(splashScreen)
        splashScreen->changeSplashScreenLayout(layout);
}

void OLApplication::dismissSplashScreen()
{
    OLSplashScreen* splashScreen = m_mainwidget->findChild<OLSplashScreen*>();
    if(splashScreen)
        splashScreen->dismissSplashScreen();
}

// ---------------------------
// View handling
// ---------------------------

void OLApplication::setView(QWidget* view, OrientationOptions options, bool keep)
{
    m_appWindow->setView(view, options, keep);
}

void OLApplication::addStackedView(QWidget* view, OrientationOptions options, bool keep)
{
    m_appWindow->addStackedView(view, options, keep);
}

QWidget* OLApplication::currentView() const
{
    return m_appWindow->currentView();
}

QWidget* OLApplication::viewParent() const
{
    return m_appWindow;
}

// ---------------------------
// Toolbar handling
// ---------------------------

OLButtonList OLApplication::toolbarButtons() const
{
    return m_toolbar->findChildren<OLButton*>();
}

void OLApplication::addToolbarButton(OLButton* button, const OLWidgetList& hideForMini)
{
    m_hideForLandscape.append(hideForMini);
    button->setMinimumWidth(FINGER_SIZE);
    button->opaque();
    m_toolbar->layout()->addWidget(button);

    if(orientation()==landscape) {
        int wgtCount = hideForMini.count();
        for(int ii=0; ii<wgtCount; ++ii)
            hideForMini[ii]->hide();
    }
}

void OLApplication::hideToolbar()
{
    m_toolbar->hide();
}

void OLApplication::showToolbar()
{
    m_toolbar->show();
}

void OLApplication::miniToolbar()
{
    m_miniToolbar = true;

    if( m_mainwidget->orientation()==portrait ) {
        int wgtCount = m_hideForLandscape.count();
        for(int ii=0; ii<wgtCount; ++ii)
            m_hideForLandscape[ii]->hide();
        m_toolbar->setFixedHeight(STATUSBAR_HEIGHT);
    }
}

void OLApplication::fullToolbar()
{
    m_miniToolbar = false;

    if( m_mainwidget->orientation()==portrait ) {
        int wgtCount = m_hideForLandscape.count();
        for(int ii=0; ii<wgtCount; ++ii)
            m_hideForLandscape[ii]->show();
        m_toolbar->setFixedHeight(TOOLBAR_HEIGHT);
    }
}

void OLApplication::topToolbarPosition()
{
    if( m_toolbarBottomPos && m_mainwidget->orientation()==portrait ) {
        QVBoxLayout* layout = qobject_cast<QVBoxLayout*>(m_mainwidget->layout());
        layout->removeWidget(m_toolbar);
        layout->insertWidget(2, m_toolbar);
        m_toolbar->lower();
        m_toolbarBottomPos = false;
    }
}

void OLApplication::bottomToolbarPosition()
{
    if( !m_toolbarBottomPos && m_mainwidget->orientation()==portrait ) {
        QVBoxLayout* layout = qobject_cast<QVBoxLayout*>(m_mainwidget->layout());
        layout->removeWidget(m_toolbar);
        layout->addWidget(m_toolbar);
        m_toolbar->lower();
        m_toolbarBottomPos = true;
    }
}

void OLApplication::handleSwitchToLandscape()
{
    emit switchToLandscape();

    int wgtCount = m_hideForLandscape.count();
    for(int ii=0; ii<wgtCount; ++ii)
        m_hideForLandscape[ii]->hide();

    m_toolbar->setParent(m_statusbar);
    m_toolbar->setFixedHeight(STATUSBAR_HEIGHT);
    m_statusbar->layout()->addWidget(m_toolbar);
    m_toolbar->m_drawBg = false;
}

void OLApplication::handleSwitchToPortrait()
{
    emit switchToPortrait();

    int toolbarHeight = FINGER_SIZE;

    if( !m_miniToolbar ) {
        toolbarHeight = TOOLBAR_HEIGHT;
        int wgtCount = m_hideForLandscape.count();
        for(int ii=0; ii<wgtCount; ++ii)
            m_hideForLandscape[ii]->show();
    }

    m_toolbar->setParent(m_mainwidget);
    m_toolbar->setFixedHeight(toolbarHeight);
    QVBoxLayout* layout = qobject_cast<QVBoxLayout*>(m_mainwidget->layout());
    if( m_toolbarBottomPos )
        layout->addWidget(m_toolbar);
    else
        layout->insertWidget(2, m_toolbar);
    
    m_toolbar->lower();
    m_toolbar->m_drawBg = true;
}

void OLApplication::appResized()
{
}

// ---------------------------
// Dialog handling
// ---------------------------
int OLApplication::showDialog(const QPixmap& icon, const QString& title, QLayout* body, const OLButtonList& buttons)
{
    OLDialogSurface* dialog = new OLDialogSurface(icon, title, body, buttons, m_mainwidget);
    QSize mainSize = m_mainwidget->size();
    dialog->resize(mainSize);
    connect(m_mainwidget, SIGNAL(handleResize()), dialog, SLOT(handleParentResize()));
    connect(m_mainwidget, SIGNAL(handlePortraitSwitch()), dialog, SIGNAL(portraitSwitch()));
    connect(m_mainwidget, SIGNAL(handleLandscapeSwitch()), dialog, SIGNAL(landscapeSwitch()));
    connect(dialog, SIGNAL(dialogClosed(int)), this, SIGNAL(dialogClosed(int)));

#ifdef OL_BLUR_BACKGROUND
    // render the pixmap for the background
    QPixmap pixmap(mainSize);
    m_mainwidget->render(&pixmap);
    dialog->setBackgroundPixmap(pixmap);
#endif

    dialog->showDialog();
    return (int)dialog; // return the pointer as the id to reuse if programmatically dismissed
}

int OLApplication::showDialog(const QPixmap& icon, const QString& title, const QString& message, const OLButtonList& buttons)
{
    QLabel* messageText = new QLabel(message);
    messageText->setWordWrap(true);
    //messageText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);

    QVBoxLayout* messageLayout = new QVBoxLayout();
    messageLayout->setContentsMargins(0,10,0,10);
    messageLayout->addWidget(messageText, 0, Qt::AlignVCenter);

    return showDialog(icon, title, messageLayout, buttons);
}

void OLApplication::dismissDialog(int id)
{
    OLDialogSurface* dialog = (OLDialogSurface*)id; // the id is really the pointer
    QList<OLDialogSurface*> dialogs = m_mainwidget->findChildren<OLDialogSurface*>();
    if( dialogs.contains(dialog) ) {
        // found the dialog
        dialog->dismissDialog();
    }
}

// ---------------------------
// Text banner handling
// ---------------------------

void OLApplication::showBanner(const QString& message, bool autodismiss)
{
    QSize mainSize = m_mainwidget->size();
    OLBannerSurface* dialog = new OLBannerSurface(autodismiss, m_mainwidget);
    dialog->resize(mainSize);
    dialog->setText(message);
    connect(m_mainwidget, SIGNAL(handleResize()), dialog, SLOT(handleParentResize()));

#ifdef OL_BLUR_BACKGROUND
    // render the pixmap for the background
    QPixmap pixmap(mainSize);
    m_mainwidget->render(&pixmap);
    dialog->setBackgroundPixmap(pixmap);
#endif

    dialog->show();
}

// ---------------------------
// Menu handling
// ---------------------------

OLMenuSurface* OLApplication::getOrCreateMenuSurface()
{
    OLMenuSurface* menuSurface = m_mainwidget->findChild<OLMenuSurface*>();

    if(!menuSurface) {
        menuSurface = new OLMenuSurface(m_mainwidget);
        menuSurface->resize(m_mainwidget->size());
        connect(m_mainwidget, SIGNAL(handlePortraitSwitch()), menuSurface, SIGNAL(portraitSwitch()));
        connect(m_mainwidget, SIGNAL(handleLandscapeSwitch()), menuSurface, SIGNAL(landscapeSwitch()));
        connect(m_mainwidget, SIGNAL(handleResize()), menuSurface, SLOT(handleAppSize()));

        connect(menuSurface, SIGNAL(menuStateChange(OLMenuSurface::OLMenuState)), m_statusbar, SLOT(handleMenuState(OLMenuSurface::OLMenuState)));
    }

    return menuSurface;
}

int OLApplication::addMenuItem(const QString& menuitem, const QObject* receiver, const char* method)
{
    return getOrCreateMenuSurface()->addMenuItem(menuitem, receiver, method);
}

void OLApplication::addMenuItem(int id, const QString& menuitem, const QObject* receiver, const char* method)
{
    getOrCreateMenuSurface()->addMenuItem(id, menuitem, receiver, method);
}

void OLApplication::removeMenuItem(int id)
{
    OLMenuSurface* menuSurface = m_mainwidget->findChild<OLMenuSurface*>();

    if(menuSurface)
        menuSurface->removeMenuItem(id);
}

void OLApplication::hideMenuItem(int id)
{
    OLMenuSurface* menuSurface = m_mainwidget->findChild<OLMenuSurface*>();

    if(menuSurface)
        menuSurface->hideMenuItem(id);
}

void OLApplication::showMenuItem(int id)
{
    OLMenuSurface* menuSurface = m_mainwidget->findChild<OLMenuSurface*>();

    if(menuSurface)
        menuSurface->showMenuItem(id);


}

void OLApplication::showMenu()
{

    OLMenuSurface* menuSurface = m_mainwidget->findChild<OLMenuSurface*>();

    if(menuSurface) {
#ifdef OL_BLUR_BACKGROUND
        QSize pixmapSize(menuSurface->size());
        QPixmap pixmap(pixmapSize);
        m_mainwidget->render(&pixmap, QPoint(0, -STATUSBAR_HEIGHT));
        menuSurface->setBackgroundPixmap(pixmap);
#endif
        menuSurface->showMenu();
    }
}

void OLApplication::hideMenu()
{
    OLMenuSurface* menuSurface = m_mainwidget->findChild<OLMenuSurface*>();

    if(menuSurface)
        menuSurface->hideMenu();
}

// ---------------------------
// Info Panel handling
// ---------------------------

void OLApplication::homeButtonClicked()
{
#ifdef Q_OS_SYMBIAN
    TRawEvent lEventDown;
    lEventDown.Set(TRawEvent::EKeyDown, EStdKeyApplication0);
    UserSvr::AddEvent(lEventDown);

    User::After(700000);
    TRawEvent lEventUp;
    lEventUp.Set(TRawEvent::EKeyUp, EStdKeyApplication0);
    UserSvr::AddEvent(lEventUp);
#else
    showInfoPanel();
#endif
}

void OLApplication::showInfoPanel()
{
    OLInfoPanelSurface* panelSurface = m_mainwidget->findChild<OLInfoPanelSurface*>();

    if(!panelSurface) {
        panelSurface = new OLInfoPanelSurface(m_mainwidget);
        panelSurface->resize(m_mainwidget->size());
        connect(m_mainwidget, SIGNAL(handlePortraitSwitch()), panelSurface, SIGNAL(portraitSwitch()));
        connect(m_mainwidget, SIGNAL(handleLandscapeSwitch()), panelSurface, SIGNAL(landscapeSwitch()));
        connect(m_mainwidget, SIGNAL(handleResize()), panelSurface, SLOT(handleAppSize()));

#ifdef OL_BLUR_BACKGROUND
        QSize pixmapSize(panelSurface->size());
        QPixmap pixmap(pixmapSize);
        m_mainwidget->render(&pixmap, QPoint(0, -STATUSBAR_HEIGHT));
        panelSurface->setBackgroundPixmap(pixmap);
#endif

        panelSurface->showInfoPanel();
    }
}

void OLApplication::hideInfoPanel()
{
    OLInfoPanelSurface* panelSurface = m_mainwidget->findChild<OLInfoPanelSurface*>();

    if(panelSurface)
        panelSurface->hideInfoPanel();
}

// ---------------------------
// Spinner handling
// ---------------------------

void OLApplication::showViewSpinner(const QString& caption)
{
    OLSpinnerSurface* spinner = m_mainwidget->findChild<OLSpinnerSurface*>();

    if(!spinner) {
        QSize mainSize = m_mainwidget->size();
        OLSpinnerSurface* spinner = new OLSpinnerSurface(caption, m_mainwidget);
        spinner->setGeometry(m_appWindow->geometry());
        connect(m_appWindow, SIGNAL(handleResize(QSize)), spinner, SLOT(handleViewResize(QSize)));

    #ifdef OL_BLUR_BACKGROUND
        // render the pixmap for the background
        QPixmap pixmap(mainSize);
        m_mainwidget->render(&pixmap);
        spinner->setBackgroundPixmap(pixmap);
    #endif

        //connect(dlgBg, SIGNAL(clicked()), this, SLOT(hideSpinner()));

        spinner->show();
    } else {
        spinner->setCaption(caption);
    }
}

void OLApplication::showSpinner(const QString& caption)
{
    OLSpinnerSurface* spinner = m_mainwidget->findChild<OLSpinnerSurface*>();

    if(!spinner) {
        QSize mainSize = m_mainwidget->size();
        OLSpinnerSurface* spinner = new OLSpinnerSurface(caption, m_mainwidget);
        spinner->resize(mainSize);
        connect(m_mainwidget, SIGNAL(handleResize()), spinner, SLOT(handleAppResize()));

    #ifdef OL_BLUR_BACKGROUND
        // render the pixmap for the background
        QPixmap pixmap(mainSize);
        m_mainwidget->render(&pixmap);
        spinner->setBackgroundPixmap(pixmap);
    #endif

        //connect(dlgBg, SIGNAL(clicked()), this, SLOT(hideSpinner()));

        spinner->show();
    } else {
        spinner->setCaption(caption);
    }
}

void OLApplication::hideSpinner()
{
    OLSpinnerSurface* spinner = m_mainwidget->findChild<OLSpinnerSurface*>();
    if( spinner ) {
        delete spinner;
    }
}
